from abc import ABCMeta, abstractmethod
import os


# 整体与部分的关系或者是层次性比较明显的关系
class Component(metaclass=ABCMeta):
    """组件"""
    def __init__(self, name):
        self._name = name

    def getName(self):
        return self._name

    def isComposite(self):
        return False
    
    @abstractmethod
    def feature(self, indent):
        # indent 仅用于内容输出时的缩进
        pass


class Composite(Component):
    """复合组件"""
    def __init__(self, name):
        super().__init__(name)
        self._components = []

    def addComponent(self, component):
        self._components.append(component)

    def removeComponent(self, component):
        self._components.remove(component)

    def isComposite(self):
        return True

    def feature(self, indent):
        indent += "\t"
        for component in self._components:
            component.feature(indent)


class FileDetail(Component):
    """文件详情"""
    def __init__(self, name):
        super().__init__(name)
        self._size = 0

    def setSize(self, size):
        self._size = size

    def getSize(self):
        return self._size

    def feature(self, indent):
        fileSize = round(self._size / float(1024), 2)
        print("文件名称：%s, 文件大小：%sKB" % (self._name, fileSize))


class FolderDetail(Composite):
    def __init__(self, name):
        super().__init__(name)
        self._count = 0

    def setCount(self, fileNum):
        self._count = fileNum

    def getCount(self):
        return self._count

    def feature(self, indent):
        print("文件夹名：%s, 文件数量：%d。包含的文件：" % (self._name, self._count))
        super().feature(indent)


def scanDir(rootPath, folderDetail):
    if not os.path.isdir(rootPath):
        raise ValueError("rootPath不是有效的路径：%s" % rootPath)
    if folderDetail is None:
        raise ValueError("folderDetail不能为空")
    fileNames = os.listdir(rootPath)
    for fileName in fileNames:
        filePath = os.path.join(rootPath, fileName)
        if os.path.isdir(filePath):
            folder = FolderDetail(fileName)
            scanDir(filePath, folder)
            folderDetail.addComponent(folder)
        else:
            fileDetail = FileDetail(fileName)
            fileDetail.setSize(os.path.getsize(filePath))
            folderDetail.addComponent(fileDetail)
            folderDetail.setCount(folderDetail.getCount()+1)


def testDir():
    folder = FolderDetail("sdk")
    scanDir(r"D:\Tencent\QQ\QQFile\1806521378\FileRecv\day32-后台视频管理\node_modules\@baiducloud\sdk", folder)
    folder.feature("")


if __name__ == "__main__":
    testDir()
